﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RSSReader.DAL;
using System.Data.Entity;
using Microsoft.AspNet.Identity.EntityFramework;
using System.Data.Entity.Validation;

namespace RSSReader.Repository
{
  public class RssRepository : IRssRepository
  {

    #region Generalities

    private ApplicationDbContext _context;

    public RssRepository()
    {
      this._context = ApplicationDbContext.Create();
      this._context.Configuration.LazyLoadingEnabled = false;
    }

    public void SaveChanges()
    {
      //this._context.SaveChanges();
        try
        {
            this._context.SaveChanges();
        }
        catch (DbEntityValidationException e)
        {
            foreach (var eve in e.EntityValidationErrors)
            {
                Console.WriteLine("Entity of type \"{0}\" in state \"{1}\" has the following validation errors:",
                    eve.Entry.Entity.GetType().Name, eve.Entry.State);
                foreach (var ve in eve.ValidationErrors)
                {
                    Console.WriteLine("- Property: \"{0}\", Error: \"{1}\"",
                        ve.PropertyName, ve.ErrorMessage);
                }
            }
            throw;
        }
    }

    #endregion

    #region User

    public ApplicationUser GetUserByUserName(string userName)
    {
      return this._context.Users.Where(w => w.UserName == userName).FirstOrDefault();
    }

    public ApplicationUser GetUser(string id)
    {
      var User = this._context.Users.Where(w => w.Id == id).FirstOrDefault();
      return User;
    }

    public ApplicationUser GetUser(string userName, string passwordHash)
    {
      return this._context.Users.Where(w => w.UserName == userName && w.PasswordHash == passwordHash).FirstOrDefault();
    }

    public IEnumerable<ApplicationUser> GetUsers()
    {
      return this._context.Users;
    }

    public void AddUser(ApplicationUser user)
    {
      this._context.Users.Add(user);
    }

    #endregion

    #region Subscription

    public IEnumerable<UserSubscriptionVW> GetUserSubscriptions(string userId)
    {
      var Request = String.Format("select * from dbo.UserSubscriptionVW where UserId = '{0}' and IsSubscribe = 1", userId);
      return this._context.Database.SqlQuery<UserSubscriptionVW>(Request);
    }

    public IEnumerable<Source> GetSources()
    {
      return this._context.Sources;
    }

    public IEnumerable<Source> GetSources(IEnumerable<string> urls)
    {
      return this._context.Sources.Where(w => urls.Contains(w.Url));
    }

    public IEnumerable<Source> GetSources(IEnumerable<int> sourceIds)
    {
      return this._context.Sources.Where(w => sourceIds.Contains(w.Id));
    }

    public void AddSource(Source source)
    {
      this._context.Sources.Add(source);
    }

    public IEnumerable<Subscription> GetSubscriptions(string userId)
    {
      return this._context.Subscriptions.Where(w => w.UserId == userId);
    }

    public IEnumerable<Subscription> GetSubscriptions(string userId, IEnumerable<int> sourceIds)
    {
      return this._context.Subscriptions.Where(w => w.UserId == userId && sourceIds.Contains(w.SourceId));
    }

    public void AddSubscription(Subscription sub)
    {
      this._context.Subscriptions.Add(sub);
    }

    #endregion

    #region Articles

    public IEnumerable<Article> GetArticles(IEnumerable<string> url)
    {
      return this._context.Articles.Where(w => url.Contains(w.Url));
    }

    public void AddArticle(Article article)
    {
      this._context.Articles.Add(article);
    }

    public IEnumerable<UserArticle> GetUserArticles(string userId, IEnumerable<int> articleIds)
    {
      return this._context.UsersArticles.Where(w => w.UserId == userId && articleIds.Contains(w.ArticleId));
    }

    public void AddUserArticle(UserArticle userArticle)
    {
      this._context.UsersArticles.Add(userArticle);
    }

    public IEnumerable<UserArticleVW> GetUserArticlesVW(string userId, IEnumerable<string> urls)
    {
      string InClause = "";
      var Urls = urls.ToArray();

      for (int i = 0; i < Urls.Length; ++i)
      {
        if (i != 0)
          InClause += ", ";
        InClause += String.Format("'{0}'",Urls[i]);
      }

      string Request = String.Format("select * from dbo.UserArticleVW where UserId = '{0}' and Url in ({1})", userId, InClause);
      return this._context.Database.SqlQuery<UserArticleVW>(Request);
    }

    public IEnumerable<UserArticleVW> GetUserFavorites(string userId)
    {
      string Request = String.Format("select * from dbo.UserArticleVW where UserId = '{0}' and IsFavorite = 1", userId);
      return this._context.Database.SqlQuery<UserArticleVW>(Request);
    }

    #endregion
  }
}
